package Hxw3DEngine.core.materials.shader.filters {
	
	import flash.utils.ByteArray;
	import Hxw3DEngine.core.Resource.geometry.ResourceGeometry;
	import Hxw3DEngine.core.materials.shader.utils.VcRegisterLabel;
	import Hxw3DEngine.core.materials.shader.utils.ShaderRegisterCache;
	import Hxw3DEngine.core.materials.shader.utils.ShaderRegisterElement;
	
	/**
	 * 3x4矩阵骨骼动画 
	 * @author Neil
	 * 
	 */	
	public class SkeletonFilter34 extends SkeletonFilterBase {
		
		public function SkeletonFilter34() {
			super("SkeletonFilter34");
		}
		
		override public function getVertexCode(regCache:ShaderRegisterCache):String {
			super.getVertexCode(regCache);
			var bones : ShaderRegisterElement = regCache.getVc(MAX_MATRIX34_BONE * 3, boneLabel,"骨骼");
			var vc123 : ShaderRegisterElement = regCache.getVc(1, new VcRegisterLabel(Vector.<Number>([3 * 255, 1, 2, 3])),"vc123");
			var useNormal : Boolean = regCache.useNormal();
			
			var indexConst:uint = vc123.index;
			var indexOffset0:uint = bones.index;
			
			var indexStream:ShaderRegisterElement = regCache.getVa(ResourceGeometry.SKIN_INDICES);
			var weightStream:ShaderRegisterElement = regCache.getVa(ResourceGeometry.SKIN_WEIGHTS);
			var indices:Array = [ indexStream + ".x", indexStream + ".y", indexStream + ".z", indexStream + ".w" ];
			var weights:Array = [ weightStream + ".xxxx", weightStream + ".yyyy", weightStream + ".zzzz", weightStream + ".wwww" ];			
			
			var temp1 : ShaderRegisterElement = regCache.getVt("空闲的VT1");
			var temp2 : ShaderRegisterElement = regCache.getVt("空闲的VT2");
			var temp3 : ShaderRegisterElement = regCache.getVt("空闲的VT3");
			var m3x:String = "m34";
			
			var _jointsPerVertex:uint = 4;
			var _sourceRegisters:Vector.<ShaderRegisterElement> = new <ShaderRegisterElement>[regCache.getVa(ResourceGeometry.POSITION)];
			if (useNormal) {
				_sourceRegisters.push(regCache.getVa(ResourceGeometry.NORMAL));
			}
			var _targetRegisters:Vector.<ShaderRegisterElement> = new <ShaderRegisterElement>[regCache.op];
			var nrm : ShaderRegisterElement = null;
			if (useNormal) {
				nrm = regCache.getVt("空闲的VT4");
				_sourceRegisters.push(nrm);
			}
			var len:uint = _sourceRegisters.length;
			
			var code : String = '';
			
			for (var i:uint = 0; i < len; ++i) {

				var src:String = _sourceRegisters[i].toString();

				for (var j:uint = 0; j < _jointsPerVertex; ++j) {
					code += "mul " + temp3 + ".x, " + indices[j] + ", vc" + indexConst + ".x\n" ;
					code += m3x + " " + temp1 + ".xyz, " + src + ", vc[" + temp3 + ".x+" + indexOffset0 + "]		\n" +
							"mov " + temp1 + ".w, " + src + ".w		\n" +
							"mul " + temp1 + ", " + temp1 + ", " + weights[j] + "\n"; // apply weight

					// add or mov to target. Need to write to a temp reg first, because an output can be a target
					if (j == 0)
						code += "mov " + temp2 + ", " + temp1 + "\n";
					else
						code += "add " + temp2 + ", " + temp2 + ", " + temp1 + "\n";
				}
				// switch to dp3 once positions have been transformed, from now on, it should only be vectors instead of points
				m3x = "m33";
				code += "mov " + _targetRegisters[i] + ", " + temp2 + "\n";
			}
			
			if (useNormal) {
				code += 'm33 ' + nrm + '.xyz, ' + nrm + '.xyz, ' + regCache.vcWorld + ' \n';
				code += 'nrm ' + regCache.getV(ResourceGeometry.NORMAL) + '.xyz, ' + nrm + '.xyz \n';
			}
			
			regCache.removeVt(temp3);
			regCache.removeVt(temp2);
			regCache.removeVt(temp1);
			
			if (useNormal) {
				regCache.removeVt(nrm);
			}			
			
			return code;
		}
			
		
	}
}
